package com.yifeng.repo.micro.service.server.engine.dal.dsx;

import com.baomidou.dynamic.datasource.support.DataSourceClassResolver;
import com.gomcarter.frameworks.base.common.AssertUtils;
import com.gomcarter.frameworks.base.context.SpringContextHolder;
import com.gomcarter.frameworks.base.exception.CustomException;
import com.google.common.base.Strings;
import com.yifeng.base.bds.api.store.dto.StoreCorporationRegionInfoDto;
import com.yifeng.repo.base.mdm.full.holder.StoreRouteHolder;
import com.yifeng.repo.base.security.context.manager.RequestContextManager;
import com.yifeng.repo.base.security.context.manager.RequestHeaderManager;
import com.yifeng.repo.micro.service.server.engine.configure.ServerEngineDaoProperties;

import java.lang.reflect.Method;
import java.util.Optional;

import static com.yifeng.repo.base.constant.BaseConstant.*;

/**
 * Created by daibing on 2024/6/18.
 */
public class ProvinceDataSourceClassResolver extends DataSourceClassResolver {

    public ProvinceDataSourceClassResolver(boolean allowedPublicOnly) {
        super(allowedPublicOnly);
    }

    @Override
    public String findKey(Method method, Object targetObject) {
        // 获取DS注解里的内容，如果是按省拆库和多库混合查询就做二次路由，其他就直接返回
        String key = super.findKey(method, targetObject);
        switch (key) {
            case DS_PROVINCE_KEY:
                return getProvinceKey(method);
            case DS_MAIN_HOT_ARCHIVE_KEY:
                return getMixKey(method);
            default:
                return key;
        }
    }

    /**
     * 省库查询做二次路由
     */
    private String getProvinceKey(Method method) {
        // 1. 开始省库二次路由：检查sharding门店编号和门店路由数据
        String shardingStoreCode = RequestContextManager.getShardingStoreCode();
        AssertUtils.notNull(shardingStoreCode, "按省拆库出错，未设置sharding门店编号：" + method.getName());
        StoreCorporationRegionInfoDto storeRoute = StoreRouteHolder.get(shardingStoreCode);
        AssertUtils.notNull(storeRoute, "按省拆库出错，未设置门店路由信息: " + shardingStoreCode);

        // 2. 检查门店归属公司，如果是独立公司编码就返回独立库对应标识
        ServerEngineDaoProperties properties = SpringContextHolder.getBean(ServerEngineDaoProperties.class);
        if (properties.getStandaloneCompanyCodes() != null
                && properties.getStandaloneCompanyCodes().contains(storeRoute.getEdifactCompanyCode())) {
            return Strings.isNullOrEmpty(properties.getStandaloneDsKey())
                    ? DS_PROVINCE_KEY + UNDER_SCORE + storeRoute.getEdifactCompanyCode()
                    : properties.getStandaloneDsKey();
        }

        // 3. 根据门店归属省份，返回省份对应标识
        return DS_PROVINCE_KEY + UNDER_SCORE + storeRoute.getProvinceCode();
    }

    /**
     * 多库混合查询做二次路由
     */
    private String getMixKey(Method method) {
        String header = Optional.ofNullable(RequestHeaderManager.get(DS_TYPE_HEADER)).orElse(DS_ARCHIVE_KEY);
        switch (header) {
            case DS_MAIN_KEY:
            case DS_HOT_KEY:
            case DS_ARCHIVE_KEY:
                return header;
            default:
                throw new CustomException(String.format("多库混合查询设置参数错误：method=%s, key=%s, value=%s",
                        method.getName(), DS_TYPE_HEADER, header));
        }
    }

}
